package com.ceba.test.modules.storage.logicService;

import com.ceba.base.enums.FileStorageFalgeEnum;
import com.ceba.base.exception.CebaException;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.enums.CopyFlagEnum;
import com.ceba.test.base.enums.StorageStatusEnum;
import com.ceba.test.modules.storage.cache.GStorageAddressCache;
import com.ceba.test.modules.storage.entity.GStorageAddress;
import com.ceba.test.modules.storage.job.StorageFileBase;
import com.ceba.test.modules.storage.job.impl.StorageFileJob;
import configs.context.SpringBeans;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.List;

/**
 * 存储文件缓存管理
 * @author Administrator
 */
public class StorageFileCacheManage {
	private static Logger logger = LoggerFactory.getLogger(StorageFileCacheManage.class);
	//系统正在使用的存储ID
	private static String SYSTEM_BEING_USED_STORAGE_ID=null;
	/**
	 * 取得当前正在使用的存储地址信息
	 * @return
	 */
	public static GStorageAddress getSystemUseStorageAddress() throws CebaException {
		if(StringUtils.isBlank(SYSTEM_BEING_USED_STORAGE_ID)){
			getAvailableStorageAddress();
		}
		String key=GStorageAddress.filterCreateRule(SYSTEM_BEING_USED_STORAGE_ID);
		GStorageAddress gStorageAddress=GStorageAddressCache.getKeyGStorageAddress(key);
		return gStorageAddress;
	}

	private static void getAvailableStorageAddress() throws CebaException {
		List<GStorageAddress> addresseList= GStorageAddressCache.getAllList();
		GStorageAddressLogicService gStorageAddressLogicService= SpringBeans.getGStorageAddressLogicService("gStorageAddressLogicService");
		if(CollectionUtils.isEmpty(addresseList)){
            List<GStorageAddress> list=gStorageAddressLogicService.sreachAll();
            if(CollectionUtils.isEmpty(list)){
                logger.debug("当前可以使用的文件存储地址不存在,请添加存储地址");
                throw new CebaException("当前可以使用的文件存储地址不存在,请添加存储地址");
            }
            GStorageAddressCache.againAllData(list);
            addresseList=GStorageAddressCache.getAllList();
        }

		//找第一个“可用”的空间地址
		for(GStorageAddress address:addresseList){
            if(StringUtils.equals(address.getStatus(), StorageStatusEnum.CAN.getCode())){
                SYSTEM_BEING_USED_STORAGE_ID=address.getId();
                break;
            }
        }

		//没有找到“可用”的空间地址，则开始找一个“未启用”的空间
		if(StringUtils.isBlank(SYSTEM_BEING_USED_STORAGE_ID)){
            /**
			 * 策略：
             * 1、找到第一个“未启用”的空间
             * 2、此空间“未拷贝”过，则转到第3步；此空间“已拷贝”过，则直接转到4
             * 3、找到一个“已拷贝”过的空间，并将空间中的“images”、“template”、“user”目录拷贝到“未启用、未拷贝”的空间，同时将“未拷贝”状态置为“已拷贝”
             * 4、将“未启用”状态置为“已启用
             */
            for(GStorageAddress address:addresseList){
                //1、找到第一个“未启用”的空间
                if(StringUtils.equals(address.getStatus(), StorageStatusEnum.NOSTART.getCode())){
                    //2、此空间“未拷贝”过
                    if (CopyFlagEnum.NOCOPY.getCode().equalsIgnoreCase(address.getCopyFlag())) {
                        //3、找到一个“已拷贝”过的空间，并将空间中的“images”、“template”、“user”目录拷贝到“未启用、未拷贝”的空间，同时将“未拷贝”状态置为“已拷贝”
                        GStorageAddress copiedAddress = gStorageAddressLogicService.searchCopiedAddress();
                        if(copiedAddress == null){
                            logger.debug("当前可以使用的文件存储地址都已经满了，没有已满的 作为拷贝源，请检查数据库存储地址的完整性");
                            throw new CebaException("当前可以使用的文件存储地址都已经满了，没有已满的 作为拷贝源，请检查数据库存储地址的完整性");
                        }

                        StorageFileBase storageFileBase = new StorageFileJob(SpringBeans.getGStorageAddressLogicService("gStorageAddressLogicService"));
                        boolean isCopySuccess = storageFileBase.copy(address, copiedAddress);
                        if(isCopySuccess){
                            gStorageAddressLogicService.editCopyFlag(address.getId(), CopyFlagEnum.COPY.getCode());
                            address.setCopyFlag(CopyFlagEnum.COPY.getCode());
                        } else {
                            logger.debug("当前可以使用的文件存储地址都已经满了，拷贝文件失败");
                            throw new CebaException("当前可以使用的文件存储地址都已经满了，拷贝文件失败");
                        }
                    }

                    //4、将“未启用”状态置为“已启用
                    gStorageAddressLogicService.editStatus(address.getId(), StorageStatusEnum.CAN.getCode());
                    address.setStatus(StorageStatusEnum.CAN.getCode());
                    SYSTEM_BEING_USED_STORAGE_ID=address.getId();
                    break;
                }
            }

            //都满了--状态都是已满
            if(StringUtils.isBlank(SYSTEM_BEING_USED_STORAGE_ID)){
                logger.debug("当前可以使用的文件存储地址都已经满了，请添加新的存储地址");
                throw new CebaException("当前可以使用的文件存储地址都已经满了，请添加新的存储地址");
            }
        }
	}

	/**
	 * 取得系统当前使用的存储ID
	 * @return
	 */
	public static String getSystemUseAddressId(){
		if(CebaConfig.FILE_STORAGE_FALG== FileStorageFalgeEnum.NOSTART){
			return CebaConfig.FILE_STORAGE_DEFAULT_ID;
		}else if(StringUtils.isEmpty(SYSTEM_BEING_USED_STORAGE_ID)){
			getSystemUseStorageAddress();
		}
		return SYSTEM_BEING_USED_STORAGE_ID;
	}
	
	/**
	 * 取得系统当前等在使用的路径
	 * @return
	 * 路径前缀 D:/ceba
	 */
	public static String getSystemUsePath(){
		try{
			GStorageAddress gStorageAddress=getSystemUseStorageAddress();
			return gStorageAddress.getPath();
		}catch(CebaException idsException){
			logger.debug(idsException.toString());
		}
		return null;
	}
	
	/**
	 * 根据ID取得存储路径
	 * @param id
	 * @return
	 */
	public static String getIDPath(String id){
		GStorageAddress gStorageAddress=GStorageAddressCache.getIDGStorageAddress(id);
		if(gStorageAddress == null){
			return null;
		}
		return gStorageAddress.getPath();
	}
	
	/**
	 * 根据ID取得过滤器路径
	 * @param id
	 * @return
	 */
	public static String getIDFilter(String id){
		GStorageAddress gStorageAddress=GStorageAddressCache.getIDGStorageAddress(id);
		if(gStorageAddress == null){
			return null;
		}
		return gStorageAddress.getFilter();
	}
	
	/**
	 * 根据过滤器取得 路径
	 * @param fileter
	 * @return
	 */
	public static String getFileterPath(String fileter){
		GStorageAddress gStorageAddress=GStorageAddressCache.getKeyGStorageAddress(fileter);
		if(gStorageAddress == null){
			return null;
		}
		return gStorageAddress.getPath();
	}
	

	/**
	 * 切换系统中使用存储 地址
	 * @param id
	 */
	public static void switchSystemUseStorageAddress(String id){
		SYSTEM_BEING_USED_STORAGE_ID=id;
	}
	/**
	 * 判断系统存储 有没有可用 的存储地址
	 * @return
	 */
	public static boolean isSystemUseStorageAddress(){
		if(CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.NOSTART){
			return true;
		}
		try{
			GStorageAddress gStorageAddress=getSystemUseStorageAddress();
			if(gStorageAddress == null){
				return false;
			}
		}catch(CebaException idsException){
			return false;
		}
		return true;
	}
	
	/**
	 * 是否不可用
	 * @return:true-不可用，磁盘空间将满;false-可用，磁盘空间未满
	 */
	public static boolean isNotUse(long minValue, GStorageAddress gStorageAddress){
		//实际剩余容量小于给定范围
		if(gStorageAddress.getRest() < minValue){
			return true;
		}
		return false;
	}
	
	/**
	 * 取得未启动的
	 * @return
	 */
	public static GStorageAddress getNoStart(){
		List<GStorageAddress> addresseList=GStorageAddressCache.getAllList();
		if(CollectionUtils.isEmpty(addresseList)){
			return null;
		}
		for(GStorageAddress address:addresseList){
			if(StringUtils.equals(address.getStatus(), StorageStatusEnum.NOSTART.getCode())){
				return address;
			}
		}
		return null;
	}
	/**
	 * 判断当前系统 使用空间是否需要提示
	 * 1.没有未启动的
	 * 2.当前可用的 小于  IIDSConfig.FILE_STORAGE_HINT_VALUE
	 * @return true-系统空间不够需要提示；false-空间足够不需要提示
	 */
	public static boolean isSystemUseSpaceHint(){
		if(CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.START && StorageFileCacheManage.getNoStart() == null){
			return isNotUse(CebaConfig.FILE_STORAGE_HINT_VALUE, getSystemUseStorageAddress());
		}
		return false;
	}

	/**
	 * 判断当前系统 使用空间是否需要禁止使用
	 * 1.没有未启动的
	 * 2.当前可用的 小于  IIDSConfig.FILE_STORAGE_CHANGE_VALUE
	 * @return true-系统空间不够禁止使用；false-空间足够允许使用
	 */
	public static boolean isSystemUseSpaceDisable(){
		if(CebaConfig.FILE_STORAGE_FALG == FileStorageFalgeEnum.START && StorageFileCacheManage.getNoStart() == null){
			return isNotUse(CebaConfig.FILE_STORAGE_CHANGE_VALUE, getSystemUseStorageAddress());
		}
		return false;
	}


}
